﻿using LitJson;
using System;
using System.Collections.Generic;
using System.Data;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using UnityEngine;
using System.Xml.Serialization;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

public delegate int responseCall(string str);
public delegate void Callback<T>(T t);

public class HttpManager
{
    bool connect;
    string url;
    public string token;
    long reqStamp;

    public HttpManager()
    {
        // this.connect = connect;
        // this.url = url;
        Init();
    }

    public void OnUpdate()
    {
        HttpResponseHandler();
    }
    public void Get(string url, Callback<string> callback, Dictionary<string, object> parameters = null)
    {
        HttpConnection request = new HttpConnection(url, HttpMethod.GET);
        request.dataHandler = (HttpConnection response) =>
        {
            callback?.Invoke(response.GetText());
        };
        request.completeEvent = () =>
        {
            AddHttpResponseQueue(request);
        };
        if (parameters != null && parameters.Count > 0)
        {
            foreach (string key in parameters.Keys)
            {
                request.AddParameter(key, parameters[key].ToString());
            }
        }
        AddHttpRequestQueue(request);
    }

    public static int BytesToSByte()
    {
        return 1;
    }

    public void luaToCPost(string Url, Dictionary<string, string> jsonStr = null, responseCall call = null)
    {
        if (jsonStr != null)
        {
            Post(Url, async (string str) =>
            {
                //responseCall _responseCall = XLuaManager.Instance().Global<responseCall>("ResponseDataFun");
                // JsonData jd = JsonMapper.ToObject(str);
                // var a = SerializeList.ListFromJson<string>(str);
                // Debug.Log("Main.Data.token====================================="+ a);
                //responseData["code"] = (int)jd["code"];
                //_responseCall(str);
                call?.Invoke(str);
            }, JsonMapper.ToJson(jsonStr));
        }
        else
        {
            Post(Url, (string str) =>
            {
                //responseCall _responseCall = XLuaManager.Instance().Global<responseCall>("ResponseDataFun");
                //JsonData jd = JsonMapper.ToObject(str);
                ////responseData["code"] = (int)jd["code"];
                //_responseCall(str);
                call?.Invoke(str);
            });
        }

    }
    //public void requestDataArray(string Url, Dictionary<string, string> jsonStr)
    //{
    //    Debug.Log("Post  " + url + "jsonStr  " + jsonStr);

    //    string data = jsonStr["players"];
    //    string[] strArray = data.Split(','); //字符串转数组
    //    Dictionary<string, int[]> jsonStr2 = new Dictionary<string, int[]>();
    //    if (strArray[0] == "")
    //    {
    //        int[] intArray2 = new int[0];
    //        jsonStr2.Add("players", intArray2);
    //    }
    //    else
    //    {
    //        int[] intArray = new int[strArray.Length];
    //        for (int i = 0; i < strArray.Length; i++)
    //        {
    //            intArray[i] = int.Parse(strArray[i]);
    //        }

    //        jsonStr2.Add("players", intArray);
    //        // jsonStr["players"] = strArray;
    //        Debug.Log("Post  " + url + "jsonStr  " + jsonStr);
    //    }


    //    Post(Url, async (string str) =>
    //    {
    //        responseCall _responseCall = XLuaManager.Instance().Global<responseCall>("ResponseDataFun");
    //        _responseCall(str);
    //    }, JsonMapper.ToJson(jsonStr2));
    //}
    //public void SetToken(string token)
    //{
    //    Main.Data.token = token;
    //    // Debug.Log("Main.Data.token======"+ token);
    //}
    public void Post(string url, Callback<string> callback, string jsonStr = "")
    {
        Debug.Log("Post  " + url + "jsonStr  " + jsonStr);
        // Main.UI.WaitRequest(url, callback);

        //Main main = GameObject.FindObjectOfType<Main>();
        //main.StartCoroutine(TempPost(url, jsonStr));

        //return;
        HttpConnection request = new HttpConnection(url, HttpMethod.POST);
        request.contentType = ContentType.JSON;
        request.dataHandler = (HttpConnection response) =>
        {
            var time = (Tools.GetCurrentTimeStamp_Long() - reqStamp) / 1000f;
            Debug.Log("地址：" + url + "\n用时：" + time + "s");
            string text = response.GetText();
            Debug.Log(text);
            // Main.UI.RemoveWaitRequest(url);
            callback?.Invoke(text);
        };
        request.completeEvent = () =>
        {
            AddHttpResponseQueue(request);
        };
        if (!string.IsNullOrEmpty(jsonStr))
        {
            request.AddJson(jsonStr);
        }
        AddHttpRequestQueue(request);
    }

    System.Collections.IEnumerator TempPost(string url, string json)
    {
        Dictionary<string, string> hearers = new Dictionary<string, string>();
        hearers.Add("Content-Type", "application/json");

        byte[] data = System.Text.Encoding.Default.GetBytes(json);

        WWW www = new WWW(url, data, hearers);
        yield return www;
        if (!string.IsNullOrEmpty(www.error))
        {
            Debug.LogError(www.error);
        }
        else
        {
            Debug.Log(www.text);
        }
    }

    public Decimal ChangeDataToD(string strData)
    {
        Decimal dData = 0.0M;
        if (strData.Contains("E"))
        {
            dData = Convert.ToDecimal(Decimal.Parse(strData.ToString(), System.Globalization.NumberStyles.Float));
        }
        return dData;
    }
    private Queue<HttpConnection> _request_queue;
    private Queue<HttpConnection> _response_queue;
    private AutoResetEvent _pause_event;
    private Thread _http_thread;
    private object _request_lock = new object();
    private object _response_lock = new object();
    private bool _thread_running = true;

    private void Init()
    {
        _request_queue = new Queue<HttpConnection>();
        _response_queue = new Queue<HttpConnection>();
        _pause_event = new AutoResetEvent(false);
        ThreadStart ts = new ThreadStart(HttpRequestHandler);
        _http_thread = new Thread(ts);
        _http_thread.Start();
    }

    public void Release()
    {
        _thread_running = false;
        _http_thread.Abort();
        _http_thread = null;
        _request_queue.Clear();
        _response_queue.Clear();
    }

    private void HttpRequestHandler()
    {
        while (_thread_running)
        {
            if (_request_queue.Count == 0)
            {
                _pause_event.WaitOne();
            }
            else
            {
                HttpConnection request;
                lock (_request_lock)
                {
                    request = _request_queue.Dequeue();
                }
                reqStamp = Tools.GetCurrentTimeStamp_Long();
                request.Send();
            }
        }
    }

    private void HttpResponseHandler()
    {
        if (_response_queue.Count > 0)
        {
            int count = _response_queue.Count;
            lock (_request_lock)
            {
                for (int i = 0; i < count; i++)
                {
                    HttpConnection response = _response_queue.Dequeue();
                    response.Callback();
                }
            }
        }
    }

    private void AddHttpRequestQueue(HttpConnection request)
    {
        lock (_request_lock)
        {
            _request_queue.Enqueue(request);
        }
        _pause_event.Set();
    }

    private void AddHttpResponseQueue(HttpConnection response)
    {
        lock (_response_lock)
        {
            _response_queue.Enqueue(response);
        }
    }

    public static string GetMd5Dec(string myString)
    {
        try
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] fromData = Encoding.UTF8.GetBytes(myString);
            byte[] targetData = md5.ComputeHash(fromData);
            StringBuilder decByt = new StringBuilder();
            decByt.Clear();
            for (int i = 0; i < targetData.Length; i++)
            {
                decByt.Append(targetData[i].ToString("x2"));
            }
            return decByt.ToString().ToLower();
        }
        catch
        {
            return "";
        }
    }
}
public class ReqData_EmailLogin
{
    public string email;
    public string pwd;
}
public class ResData_EmailLogin
{
    public int code;
    public EmailLoginData data;
    public string i18n;
    public string msg;
}
public class EmailLoginData
{
    public string avatar;
    public bool bot;
    public string nickname;
    public int online;
    public int orgId;
    public int ouid;
    public int status;
    public string token;
    public int uid;
}